const fs = require('fs');
const cmd = require('child_process');
const express = require('express')
const app = express()

var jsonArr = null;          //视频配置数据
var isMyAutoClose = false;   //是否主动关闭进程
var path1 = __dirname+'/www/data.json'
var path2 = __dirname+'/www/hls/';



//设置静态文件路径
app.use(express.static('www'));
//允许跨域
app.all('*',function(req, res, next){
  res.header("Access-Control-Allow-Origin", "*");   
  next();
})
//路由设置
app.get('/', function (req, res) {
  res.send('hello world')
})


//接受 post 传给接口 /commit 的数据
app.use('/commit',function(req,res,next){
  var data = '';
  //监听数据流事件，默认二进制流，使用+号是自动toString转化位字符
  req.on('data', function (chunk) {
    data += chunk;
  });
  //监听数据接受完成事件
  req.on('end', function () {
    jsonArr = JSON.parse(data);
    //写入文件
    fs.writeFile(path1, JSON.stringify(jsonArr,null,2), error => {
      if(error){
        var obj = { code:'0',msg:error.message }  
      }else{
        var obj = { code:'1',msg:'ok' } 
        runFFmpeg(path2) 
      }
      res.send(JSON.stringify(obj))
    });
  });
})  
app.listen(2000);
console.log("打开\033[32m http://localhost:2000/index.html \033[0m设置启动推流");

//数据重置操作
resetData(path1)
resetAction(path2)


/***********************************相关函数***************************************/
  //删除文件价及里面的文件
  function delDir(path){
    let files = [];
    if(fs.existsSync(path)){
      files = fs.readdirSync(path);
      files.forEach((file, index) => {
        let curPath = path + "/" + file;
        if(fs.statSync(curPath).isDirectory()){
          delDir(curPath); //递归删除文件夹
        } else {
          fs.unlinkSync(curPath); //删除文件
        }
      });
      fs.rmdirSync(path);
    }
  }

  //执行命令，关闭进程操作
  function viewProcessMessage (name, cb) {
    let cmdStr = process.platform === 'win32' ? 'tasklist' : 'ps aux'
    cmd.exec(cmdStr, function (err, stdout, stderr) {
      if (err) {
        return console.error(err)
      }
      stdout.split('\n').filter((line) => {
        let processMessage = line.trim().split(/\s+/)
        let processName = processMessage[0] //processMessage[0]进程名称 ， processMessage[1]进程id
        if (processName === name) {
          return cb(processMessage[1])
        }
      })
    })
  }

  //重置操作，关闭指定进程，删除相关文件
  function resetAction(path){
    isMyAutoClose = true;
    viewProcessMessage('ffmpeg.exe',function (id) {
      process.kill(id)            //关闭匹配的进程
      delDir(path)
    })    
  }

  //重置操作，重置配置数据 data.json
  function resetData(path){
    var json = fs.readFileSync(path, 'utf-8');
    jsonArr = JSON.parse(json);   
    jsonArr.forEach(function(v){
      v.error = '';
      v.iswork = true;
    }) 
    fs.writeFileSync(path, JSON.stringify(jsonArr,null,2));    
  }


  //执行一个拉流推流进程
  function cmd_ffmpeg(url,key,path,isTC){ 
    if(isTC){   //转码（注：转码非常消耗电脑性能，最多不超过5个）
      var cmdStr = 'ffmpeg -i '
          +url
          +' -vcodec libx264 -acodec aac -preset ultrafast -tune zerolatency'   //新视频格式需要转码
          +' -f hls '
          +'-hls_time 5 '                                      //切片间隔3s
          +'-hls_flags delete_segments -hls_list_size 2 '      //保留切片设置
          +'-hls_segment_filename '+path+key+'-%d.ts '         //重命名切片的名字：test-1.ts,test-2.ts,......
          +path+key+'.m3u8';  
    }else{     //不转码
      var cmdStr = 'ffmpeg -i '
          +url
          +' -c copy -f hls '
          +'-hls_time 5 '                                      //切片间隔3s
          +'-hls_flags delete_segments -hls_list_size 2 '      //保留切片设置
          +'-hls_segment_filename '+path+key+'-%d.ts '         //重命名切片的名字：test-1.ts,test-2.ts,......
          +path+key+'.m3u8';  
    }

    cmd.exec(cmdStr,function(err,stdout,stderr){
      if(err){
        if(isMyAutoClose) return;    //主动关闭进程时，不处理
        console.log('错误!')
        jsonArr.forEach(function(v){
          if(v.key == key){
            v.iswork = false;
            v.error = stderr;
          }
        })  
        fs.writeFileSync(__dirname+'/www/data.json', JSON.stringify(jsonArr,null,2));
      }else{
        console.log('结束！');  //输出运行结果
      }
    })
  }

  //再次拉流推流系列操作
  function runFFmpeg(path,arr){
    resetAction(path)
    //延迟5秒
    var arr = arr || jsonArr
    setTimeout(function(){
      isMyAutoClose = false         //关闭主动关闭进程状态
      try{
        fs.mkdirSync(path,'0755')   //重新创建hls文件夹
      }catch(er){

      }      
      arr.forEach(function(v){
        if(v.iswork) cmd_ffmpeg(v.url, v.key, path, v.isTC);    //终端里执行命令
      })
    },5000)
  }
